﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Reflection;
using System.Text;

using log4net;
using Newtonsoft.Json;
using FluentValidation;

namespace CashFlow.Admin.Filters
{
    public class ValidatorFilterAttribute : ActionFilterAttribute
    {
        private static ILog _logger = LogManager.GetLogger(typeof(ValidatorFilterAttribute));
        private Type _typeValidator;

        public ValidatorFilterAttribute(Type typeValidator)
        {
            _typeValidator = typeValidator;
        }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            object param = null;
            string paramName = "";
            foreach (var item in filterContext.ActionParameters)
            {
                var type = item.Value.GetType();
                if (type.FullName.EndsWith("Model"))
                {
                    param = item.Value;
                    paramName = item.Key;
                    break;
                }
            }

            bool isAbandon = true;
            string errorMsg = "";
            if (param != null)
            {
                try
                {
                    var obj = Activator.CreateInstance(_typeValidator);
                    var mi = _typeValidator.GetMethod("Validate", new Type[] { param.GetType() });
                    if (mi != null)
                    {
                        var obj2 = mi.Invoke(obj, new object[] { param });
                        var type2 = obj2.GetType();
                        var pi = type2.GetProperty("IsValid");
                        if (pi != null)
                        {
                            bool success = (bool)pi.GetValue(obj2);
                            isAbandon = !success;
                            if (!success)
                            {
                                var pi2 = type2.GetProperty("Errors");
                                if (pi2 != null)
                                {
                                    var obj3 = pi2.GetValue(obj2);
                                    if (obj3 != null)
                                    {
                                        var pi00 = obj3.GetType().GetProperty("Item");
                                        if (pi00 != null)
                                        {
                                            var mi2 = pi00.GetGetMethod();
                                            if (mi2 != null)
                                            {
                                                var obj4 = mi2.Invoke(obj3, new object[] { 0 });
                                                if (obj4 != null)
                                                {
                                                    var type4 = obj4.GetType();
                                                    var pi4 = type4.GetProperty("ErrorMessage");
                                                    if (pi4 != null)
                                                    {
                                                        errorMsg = (string)pi4.GetValue(obj4, null);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.Fatal(ex);
                }
            }

            if (isAbandon)
            {
                string json = JsonConvert.SerializeObject(param);
                string text = string.Format("Validate Model Exception, Function: {0}.{1}: {2}, {3}: {4}"
                    , filterContext.ActionDescriptor.ControllerDescriptor.ControllerType
                    , filterContext.ActionDescriptor.ActionName
                    , errorMsg
                    , paramName
                    , json);
                _logger.Error(text);

                filterContext.HttpContext.Response.Clear();
                filterContext.HttpContext.Response.StatusCode = 403;
                filterContext.Result = new ContentResult
                {
                    Content = "403",
                    ContentEncoding = Encoding.UTF8
                };
            }
        }
    }
}